大家好,今天更新了Flutter到1.22.1,它就發生錯誤了,主要是之前使用的custom_navigator package有些問題,剛好發佈了新的Navigator 2.0 API
就來試試吧!
這篇我是按照Learning Flutter’s new navigation and routing system裡面的程式做的
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.1, on Mac OS X 10.15.6 19G2021, locale zh-Hant-TW)
[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[✓] Xcode - develop for iOS and macOS (Xcode 12.0)
[✓] Android Studio (version 4.0)
[✓] Connected device (2 available)
先前說過不想讓底部導航欄消失,是因為我們跳轉頁面的時候使用的Navigator.of(context).push()
,是去尋找最靠近的Navigator
然後跳轉頁面,這時候因為只有MaterialApp裡面有一個Navigator
所以造成底部導航欄被擋住,因此要新建一個Navigator去避免這個狀況。
//這是做底部導航欄那篇,原本此處使用CustomNavigator,改為直接用pages[currentIndex]
Scaffold(
body:pages[currentIndex],
bottomNavigationBar: BottomNavigationBar()
pages裡面放等下要建的Navigator
List<Widget> pages = [
HomeNavigator(),
SearchingPage(),
ComingSoonPage(),
SearchingPage(),
MorePage(),
];
先建一個名為HomeNavigator的StatefulWidget,return Navigator
return Navigator(
pages: [
MaterialPage(
key: ValueKey('HomePage'),
child: HomePage(
)),
],)
這時候在HomePage
裡面點擊劇集跳轉到詳細頁面的時候使用Navigator.of(context).push()
底部導航欄就不會消失了
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) =>
SeriesDetailPage()));
},
今天我想更進一步試試看新功能,不使用push
先命一個變數來判斷pages裡面是否要出現SeriesDetailPage,點擊事件會傳到HomePage裡面
Series _selectedSeries;
_handleSeriesTapped(Series series) {
_selectedSeries = series;
setState(() {});
}
使用collection if判斷是否增加第二個頁面
pages: [
MaterialPage(
key: ValueKey('HomePage'),
child: HomePage(
onTapped: _handleSeriesTapped,
)),
if (_selectedSeries != null) //如果有點擊某個劇集這裡面就加上這頁
MaterialPage(
key: ValueKey(_selectedSeries),
child: SeriesDetailPage(series: _selectedSeries))
],
原先的HomePage
加上onTapped
,待劇集被點擊的時候呼叫
class HomePage extends StatefulWidget {
ValueChanged<Series> onTapped;
HomePage({this.onTapped});
@override
_HomePageState createState() => _HomePageState();
}
page不為null的時候onPopPage也不能為null
,要記得Navigator裡面加上onPopPage,不然會報錯。
onPopPage: (route, result) {
if (!route.didPop(result)) {
//返回失敗
return false;
}
// Update the list of pages by setting _selectedBook to null
setState(() {
_selectedSeries = null; //如果返回成功把它變null再setState
});
return true;
},
以下是HomeNavigator目前使用pages的完整程式
class HomeNavigator extends StatefulWidget {
@override
_HomeNavigatorState createState() => _HomeNavigatorState();
}
class _HomeNavigatorState extends State<HomeNavigator> {
Series _selectedSeries;
@override
Widget build(BuildContext context) {
//Navigator的构造函数中有一个pages参数。如果列表中的Page发生变化,Navigator就会更新堆栈的路由来匹配。
return Navigator(
pages: [
MaterialPage(
key: ValueKey('HomePage'),
child: HomePage(
onTapped: _handleSeriesTapped,
)),
if (_selectedSeries != null)
MaterialPage(
key: ValueKey(_selectedSeries),
child: SeriesDetailPage(series: _selectedSeries))
],
onPopPage: (route, result) {
print("route: $route result: $result");
if (!route.didPop(result)) {
return false;
}
// Update the list of pages by setting _selectedSeries to null
setState(() {
_selectedSeries = null;
});
return true;
},
);
}
_handleSeriesTapped(Series series) {
_selectedSeries = series;
setState(() {});
}
}
附上今天的效果圖
這次更新還有一大部分是跟Router有關,我目前還沒有找到太多相關的資料,這個資料的來源是做一個網頁的例子,也還沒找到有什麼其他例子可以學習。
GitHub連結: flutter-netflix-clone